import Taro from '@tarojs/taro'
import { View, Text } from '@tarojs/components'
import PropTypes from 'prop-types'
import classNames from 'classnames'
import AtComponent from '../../common/component'
import AtIcon from '../icon/index'

const iconTypes = {
  info: '',
  success: 'check-circle-o',
  error: 'close-circle-o',
  warning: 'exclamation-circle-o',
  offline: 'frown-o',
  loading: 'loading-3-quarters'
}
const defaultState = {
  mask: false,
  content: '',
  type: 'info',
  duration: 3,
  onClose: () => {}
}
export default class AtToast extends AtComponent {
  constructor () {
    super(...arguments)
    this.state = {
      _onClose: defaultState.onClose,
      _mask: defaultState.mask,
      _isOpened: false,
      _content: defaultState.content,
      _type: defaultState.type,
      _duration: defaultState.duration
    }
    this._timer = null
  }

  bindMessageListener () {
    Taro.eventCenter.off('atToast')
    Taro.eventCenter.on('atToast', (options = {}) => {
      const {
        content = defaultState.content,
        type = defaultState.type,
        duration = defaultState.duration,
        mask = defaultState.mask,
        onClose = defaultState.onClose,
        isOpened = true
      } = options
      const newState = {
        _onClose: onClose,
        _mask: mask,
        _isOpened: true,
        _content: content,
        _type: type,
        _duration: duration
      }
      if (isOpened) {
        this.setState(newState, () => {
          clearTimeout(this._timer)
          // 当 duration = 0 时，onClose 无效，toast 不会消失；隐藏 toast 需要手动调用 destroy
          if (duration) {
            this._timer = setTimeout(() => {
              this.setState(
                {
                  _isOpened: false
                },
                this.state._onClose
              )
            }, duration * 1000)
          }
        })
      } else {
        // destroy时立即关闭
        clearTimeout(this._timer)
        if (this.state._isOpened) {
          this.setState(
            {
              _isOpened: false
            },
            this.state._onClose
          )
        }
      }
    })
    // 绑定函数
    Taro.atToast = Taro.eventCenter.trigger.bind(Taro.eventCenter, 'atToast')
  }
  componentDidShow () {
    this.bindMessageListener()
  }

  componentDidMount () {
    this.bindMessageListener()
  }

  componentDidHide () {
    Taro.eventCenter.off('atToast')
  }

  componentWillUnmount () {
    Taro.eventCenter.off('atToast')
  }

  render () {
    const { className, customStyle } = this.props
    const { _content, _isOpened, _type, _mask } = this.state
    const isRenderIcon = _type !== 'info'

    const bodyClass = classNames('toast-body', {
      'toast-body--text': !isRenderIcon,
      [`at-toast__body--icon`]: isRenderIcon
    })

    return _isOpened ? (
      <View className={classNames('at-toast', className)}>
        {_mask && <View className='at-toast__overlay' />}
        <View className={bodyClass} style={customStyle}>
          <View className='toast-body-content'>
            {isRenderIcon && (
              <View className='toast-body-content__icon'>
                <AtIcon type={iconTypes[_type] || _type} />
              </View>
            )}
            {_content && (
              <View className='toast-body-content__info'>
                <Text>{_content}</Text>
              </View>
            )}
          </View>
        </View>
      </View>
    ) : null
  }
}

AtToast.defaultProps = {
  customStyle: {},
  className: ''
}

AtToast.propTypes = {
  customStyle: PropTypes.object,
  className: PropTypes.oneOfType([PropTypes.array, PropTypes.string])
}

export const AtToastUtil = {
  info: (content, duration, onClose, mask) => {
    Taro.atToast({
      type: 'info',
      content,
      duration,
      onClose,
      mask
    })
  },
  success: (content, duration, onClose, mask) => {
    Taro.atToast({
      type: 'success',
      content,
      duration,
      onClose,
      mask
    })
  },
  error: (content, duration, onClose, mask) => {
    Taro.atToast({
      type: 'error',
      content,
      duration,
      onClose,
      mask
    })
  },
  warning: (content, duration, onClose, mask) => {
    Taro.atToast({
      type: 'warning',
      content,
      duration,
      onClose,
      mask
    })
  },
  offline: (content, duration, onClose, mask) => {
    Taro.atToast({
      type: 'offline',
      content,
      duration,
      onClose,
      mask
    })
  },
  loading: (content, duration, onClose, mask) => {
    Taro.atToast({
      type: 'loading',
      content,
      duration,
      onClose,
      mask
    })
  },
  show: options => {
    console.log(Taro)
    Taro.atToast(options)
  },
  config: options => {
    Object.assign(defaultState, options)
  },
  destroy: () => {
    Taro.atToast({ isOpened: false })
  }
}

Taro.AtToastUtil = AtToastUtil
